import {getInitAcction} from './util'

export function createStore(reducer, defaultState) {
    let currentReducer = reducer,
        currentState = defaultState;
    let listeners = [] // 监听器数组

    // 分发action更新数据
    function dispatch(action) {
        // 校验action是否符合规范
        if (typeof action === 'undefined' || typeof action.type === 'undefined') {
            throw TypeError('action type is not defined')
        }
        if (action.__proto__ !== Object.prototype) {
            throw TypeError('action isn\'t plain object')
        }
        // 执行reducer更新数据
        currentState = currentReducer(currentState, action)
        // 遍历监听器数组依次执行
        for (let listener of listeners) {
            listener()
        }
    }
    // 返回当前状态
    function getState() {
        return currentState
    }
    // 添加监听器
    function subscribe(listener) {
        listeners.push(listener)
        return function () {
            let index = listeners.indexOf(listener)
            listeners.splice(index, 1)
        }
    }

    // 初始化dispatch
    dispatch({type: `@redux/INIT${getInitAcction(7)}`})
    return {
        dispatch,
        getState,
        subscribe
    }
}

export function bindActionCreators(actionCreators, dispatch) {
    let results = {}
    for (let key in actionCreators) {
        if (actionCreators.hasOwnProperty(key))
            results[key] = function (payload) {
                dispatch(actionCreators[key].call(this, ...arguments))
            }
    }
    return results
}

export function combineReducers(ReducersMapObject) {
    function reducer(store = {}, action) {
        if (typeof action === 'undefined' || typeof action.type === 'undefined') {
            throw TypeError('action type is not defined')
        }
        if (action.__proto__ !== Object.prototype) {
            throw TypeError('action isn\'t plain object')
        }
        let newStore = {}
        for (let key in ReducersMapObject) {
            if (Object.hasOwnProperty.call(ReducersMapObject, key)) {
                newStore[key] = ReducersMapObject[key].call(this, store[key], action)
            }
        }
        return newStore;
    }
    reducer({}, {type: `@redux/INIT${getInitAcction(7)}`})
    reducer({}, {type: `@redux/MYRETESTINIT${getInitAcction(9)}`})
    return reducer
}